<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FaceFusion API 测试</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .container {
            max-width: 700px;
            width: 100%;
            background: white;
            border-radius: 20px;
            padding: 40px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
        }

        h1 {
            color: #333;
            text-align: center;
            margin-bottom: 10px;
            font-size: 2em;
        }

        .subtitle {
            text-align: center;
            color: #666;
            margin-bottom: 30px;
        }

        .info-box {
            background: #e7f3ff;
            padding: 15px;
            border-radius: 10px;
            margin-bottom: 25px;
            border-left: 4px solid #2196F3;
        }

        .info-box p {
            color: #555;
            font-size: 0.9em;
            line-height: 1.6;
            margin: 3px 0;
        }

        .file-input {
            margin-bottom: 20px;
        }

        .file-input label {
            display: block;
            margin-bottom: 8px;
            color: #333;
            font-weight: 600;
        }

        .file-input input[type="file"] {
            width: 100%;
            padding: 12px;
            border: 2px dashed #667eea;
            border-radius: 10px;
            background: #f8f9ff;
            cursor: pointer;
            transition: all 0.3s;
        }

        .file-input input[type="file"]:hover {
            border-color: #764ba2;
            background: #f0f1ff;
        }

        .options {
            background: #f8f9fa;
            padding: 20px;
            border-radius: 10px;
            margin-bottom: 20px;
        }

        .option {
            margin-bottom: 15px;
        }

        .option:last-child {
            margin-bottom: 0;
        }

        .option label {
            display: block;
            margin-bottom: 5px;
            color: #555;
            font-size: 0.9em;
            font-weight: 500;
        }

        .option select,
        .option input[type="range"],
        .option input[type="number"] {
            width: 100%;
            padding: 8px;
            border: 1px solid #ddd;
            border-radius: 8px;
        }

        .range-value {
            float: right;
            color: #667eea;
            font-weight: 600;
        }

        button {
            width: 100%;
            padding: 15px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border: none;
            border-radius: 10px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: transform 0.3s;
        }

        button:hover:not(:disabled) {
            transform: translateY(-2px);
            box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
        }

        button:disabled {
            opacity: 0.6;
            cursor: not-allowed;
        }

        .status {
            margin-top: 20px;
            padding: 15px;
            border-radius: 10px;
            display: none;
        }

        .status.show {
            display: block;
        }

        .status.processing {
            background: #fff3cd;
            border-left: 4px solid #ffc107;
        }

        .status.success {
            background: #d4edda;
            border-left: 4px solid #28a745;
        }

        .status.error {
            background: #f8d7da;
            border-left: 4px solid #dc3545;
        }

        .status-title {
            font-weight: 600;
            margin-bottom: 8px;
            font-size: 1.1em;
        }

        .status-message {
            color: #666;
            font-size: 0.95em;
        }

        .download-link {
            display: inline-block;
            margin-top: 12px;
            padding: 10px 20px;
            background: #667eea;
            color: white;
            text-decoration: none;
            border-radius: 8px;
            font-weight: 600;
            transition: all 0.3s;
        }

        .download-link:hover {
            background: #764ba2;
            transform: translateY(-2px);
        }

        .server-status {
            text-align: center;
            margin-bottom: 20px;
            padding: 10px;
            border-radius: 8px;
            font-size: 0.9em;
        }

        .server-status.online {
            background: #d4edda;
            color: #155724;
        }

        .server-status.offline {
            background: #f8d7da;
            color: #721c24;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎬 FaceFusion API</h1>
        <p class="subtitle">人脸交换测试工具</p>

        <div id="serverStatus" class="server-status"></div>

        <div class="info-box">
            <p><strong>📌 使用说明：</strong></p>
            <p>1. 上传源人脸图片（清晰的正面照）</p>
            <p>2. 上传目标视频</p>
            <p>3. 选择参数（可选）</p>
            <p>4. 点击开始处理</p>
        </div>

        <form id="uploadForm">
            <div class="file-input">
                <label>📷 源人脸图片</label>
                <input type="file" id="sourceImage" accept="image/*" required>
            </div>

            <div class="file-input">
                <label>🎥 目标视频</label>
                <input type="file" id="targetVideo" accept="video/*" required>
            </div>

            <div class="options">
                <h3 style="margin-bottom: 15px; color: #333;">⚙️ 处理参数</h3>

                <div class="option">
                    <label>模型选择</label>
                    <select id="model">
                        <option value="inswapper_128" selected>inswapper_128 (推荐-快速)</option>
                        <option value="ghost_1_256">ghost_1_256 (平衡)</option>
                        <option value="simswap_256">simswap_256 (高质量)</option>
                        <option value="hyperswap_1a_256">hyperswap_1a_256 (新一代)</option>
                    </select>
                </div>

                <div class="option">
                    <label>
                        输出质量 <span class="range-value" id="qualityValue">85</span>
                    </label>
                    <input type="range" id="quality" min="50" max="100" step="5" value="85">
                </div>

                <div class="option">
                    <label>
                        处理线程数 <span class="range-value" id="threadsValue">4</span>
                    </label>
                    <input type="range" id="threads" min="1" max="8" step="1" value="4">
                </div>
            </div>

            <button type="submit" id="submitBtn">🚀 开始处理</button>
        </form>

        <div id="status" class="status"></div>
    </div>

    <script>
        const API_URL = 'http://127.0.0.1:8000';

        // 检查服务器状态
        async function checkServer() {
            const statusDiv = document.getElementById('serverStatus');
            try {
                const response = await fetch(`${API_URL}/api/health`, { timeout: 3000 });
                if (response.ok) {
                    statusDiv.className = 'server-status online';
                    statusDiv.textContent = '✅ 服务器在线';
                    return true;
                }
            } catch (error) {
                statusDiv.className = 'server-status offline';
                statusDiv.innerHTML = '❌ 服务器离线<br><small>请先运行: python api_server.py</small>';
                return false;
            }
        }

        // 页面加载时检查
        window.addEventListener('load', checkServer);

        // 更新范围滑块显示值
        document.getElementById('quality').addEventListener('input', (e) => {
            document.getElementById('qualityValue').textContent = e.target.value;
        });

        document.getElementById('threads').addEventListener('input', (e) => {
            document.getElementById('threadsValue').textContent = e.target.value;
        });

        // 显示状态
        function showStatus(type, title, message) {
            const status = document.getElementById('status');
            status.className = `status show ${type}`;
            status.innerHTML = `
                <div class="status-title">${title}</div>
                <div class="status-message">${message}</div>
            `;
        }

        // 隐藏状态
        function hideStatus() {
            document.getElementById('status').classList.remove('show');
        }

        // 表单提交
        document.getElementById('uploadForm').addEventListener('submit', async (e) => {
            e.preventDefault();

            const sourceImage = document.getElementById('sourceImage').files[0];
            const targetVideo = document.getElementById('targetVideo').files[0];

            if (!sourceImage || !targetVideo) {
                alert('请选择源图片和目标视频！');
                return;
            }

            // 检查服务器
            const serverOnline = await checkServer();
            if (!serverOnline) {
                alert('服务器未运行！\n请先执行: python api_server.py');
                return;
            }

            const submitBtn = document.getElementById('submitBtn');
            submitBtn.disabled = true;
            submitBtn.textContent = '⏳ 处理中...';

            showStatus('processing', '⏳ 处理中...', '正在上传文件并处理，请耐心等待...<br><small>这可能需要几分钟</small>');

            // 准备表单数据
            const formData = new FormData();
            formData.append('source_image', sourceImage);
            formData.append('target_video', targetVideo);
            formData.append('model', document.getElementById('model').value);
            formData.append('quality', document.getElementById('quality').value);
            formData.append('threads', document.getElementById('threads').value);

            try {
                const response = await fetch(`${API_URL}/api/face-swap`, {
                    method: 'POST',
                    body: formData
                });

                const data = await response.json();

                if (response.ok) {
                    const downloadUrl = `${API_URL}${data.download_url}`;
                    showStatus('success', '✅ 处理完成！', `
                        任务ID: ${data.task_id}<br>
                        <a href="${downloadUrl}" class="download-link" download>📥 下载视频</a>
                    `);
                } else {
                    showStatus('error', '❌ 处理失败', data.detail || '未知错误');
                }
            } catch (error) {
                showStatus('error', '❌ 错误', `${error.message}<br><small>请确保 API 服务器正在运行</small>`);
            } finally {
                submitBtn.disabled = false;
                submitBtn.textContent = '🚀 开始处理';
            }
        });
    </script>
</body>
</html>

